
#region USING STATEMENTS

using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System;

#endregion USING STATEMENTS

namespace BrickBreaker.Core
{
    public abstract class BBSingleSprite : BBSprite
    {
        #region DATA_MEMBERS
        //
            ////protected Vector2 startPosition;
        //
        #endregion DATA_MEMBERS



        #region OBJECT CONSTRUCTION
        //
            /// <summary>
            /// Creates a generic object.
            /// </summary>
            /// <param name="texture">The texture of the object.</param>
            /// <param name="position">The position of the object.</param>
            //DEFAULT Constructor
            public BBSingleSprite(Texture2D texture, Vector2 position)
            {
                base.texture = texture;
                base.position = position;
                ////this.startPosition = startPosition;//position;

                //////////////////////////////////////////////////////////////////////////
                //These data members will get assigned values inside Inherited Class...
                //////////////////////////////////////////////////////////////////////////
                base.size = Vector2.Zero;
                //this.centerOffset = size / 2;
                base.center = Vector2.Zero;//position + (this.size / 2);
                base.speed = Vector2.Zero;
                base.direction = Vector2.Zero;
            }
        //
        #endregion OBJECT CONSTRUCTION



        #region PROPERTIES
        //
            #region BASE_CLASS_PROPERTIES
            //
            public override Texture2D Texture
            {
                get { return base.texture; }
                set { base.texture = value; }
            }
            
            public override Vector2 Position
            {
                get { return base.position; }
                set { base.position = value; }
            }
            //
            //public override Vector2 Offset
            //{
            //    get 
            //    {
            //        this.centerOffset = this.size / 2;
            //        return centerOffset; 
            //    }
                //set { centerOffset = new Vector2(size.X / 2, size.Y / 2); }
            //} 
            //
            public override Vector2 Size
            {
                get { return base.size; }
                set { base.size = value; }
            }
            
            public override Vector2 Center
            {
                get
                {
                    //This center calc. ONLY works for Circle, Square and Rectangle
                    base.center = base.position + (base.size / 2);
                    return base.center;
                }
                //set { ; }
            }
            
            public override Vector2 Speed
            {
                get { return base.speed; }
                set { base.speed = value; }
            } 
            
            public override Vector2 Direction
            {
                get { return base.direction; } //this.direction; }
                set 
                { 
                    base.direction = value;
                    //Round Off to two decimal places
                    base.direction.X = (float)Math.Round(base.direction.X, 2);
                    base.direction.Y = (float)Math.Round(base.direction.Y, 2);
                }
            }
            //
            #endregion BASE_CLASS_PROPERTIES


            #region BBSingleSprite_CLASS_PROPERTIES
            ////public virtual Vector2 StartPosition
            ////{
            ////    get { return this.startPosition; }
            ////    set { this.startPosition = position; }
            ////}
            #endregion BBSingleSprite_CLASS_PROPERTIES       
        //
        #endregion PROPERTIES



        #region PUBLIC_METHODS
        //
            /// <summary>
            /// Normalizes the direction vector to ensure it's a unit vector.
            /// </summary>
            public override void DirectionNormalize()
            {
                if (base.direction != Vector2.Zero)
                {
                    base.direction.Normalize();
                }
                //Round Off to two decimal places
                base.direction.X = (float)Math.Round(base.direction.X, 2);
                base.direction.Y = (float)Math.Round(base.direction.Y, 2);
            }

            /// <summary>
            /// Checks the bounds to make sure the object doesn't go off screen.
            /// Reflects the object using simple reflection.
            /// </summary>
            public virtual void BoundaryCheck()
            {
                /******************************************************************************/
                // SPECIAL NOTE: Removed speed and added direction to change movement direction
                /******************************************************************************/

                //Checking right boundary
                ////if (position.X + size.X + speed.X > BBGlobalConfig.getWindowWidth())
                if (position.X + size.X + (speed.X * direction.X) > BBGlobalConfig.getWindowWidth())
                {
                    ////speed = new Vector2(-speed.X, speed.Y);
                    BBGlobalConfig.SetVolume(.05f);
                    BBGlobalConfig.WallCollisionSound.Play();

                    direction = new Vector2(-direction.X, direction.Y);
                }
                
                //Checking left boundary
                ////if (position.X + speed.X < 0)
                if (position.X + (speed.X * direction.X) < 0)
                {
                    ////speed = new Vector2(-speed.X, speed.Y);
                    BBGlobalConfig.SetVolume(.05f);
                    BBGlobalConfig.WallCollisionSound.Play();

                    direction = new Vector2(-direction.X, direction.Y);
                }

                //Checking upper boundary
                ////if (position.Y + speed.Y < 0)
                if (position.Y + (speed.Y * direction.Y) < 0)
                {
                    ////speed = new Vector2(speed.X, -speed.Y);
                    BBGlobalConfig.SetVolume(.05f);
                    BBGlobalConfig.WallCollisionSound.Play();

                    direction = new Vector2(direction.X, -direction.Y);
                }

                //Checking bottom boundary
                //if (position.Y + speed.Y > BBGlobalConfig.getWindowHeight())
                if (position.Y + (speed.Y * direction.Y) > BBGlobalConfig.getWindowHeight())
                {
                    ////speed = new Vector2(speed.X, -speed.Y);
                    BBGlobalConfig.SetVolume(.05f);
                    BBGlobalConfig.WallCollisionSound.Play();

                    direction = new Vector2(direction.X, -direction.Y);
                }
            }

            /// <summary>
            /// Creates a Rectangle(Box) Boundary around a sprite for box collision checks.
            /// </summary>
            public virtual Rectangle getRectBounds()
            {
                return (new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y));
            }

            /// <summary>
            /// Checks AABB collision check between this object and another to see if they intersect each other.
            /// </summary>
            public virtual bool Intersects(Rectangle rect)
            {
                return (this.getRectBounds().Intersects(rect));
            }
        //
        #endregion PUBLIC_METHODS



        #region ABSTRACT_METHODS
        //
            /// <summary>
            /// Abstract method to reset the object.
            /// </summary>
            public abstract void Reset();

            /// <summary>
            /// Abstract method to move the object.
            /// </summary>
            public abstract void Move(GameTime gameTime);

            /// <summary>
            /// Abstract method the draw the object.
            /// </summary>
            public abstract void Draw(SpriteBatch spriteBatch);
        //
        #endregion ABSTRACT_METHODS

    }//end class
}//end namespace
